
import { computed, reactive, markRaw } from 'vue'
import type {
  TStateKey,
  TAnyObject,
  IModel,
} from '../types/type'

import Model from './base-model'

export type _Method = {[key: string]: (...args: any[]) => any}

/**
 * 传入参数，创建有getter、actions 的状态 
 * @param id 状态的标志
 * @param state：状态：函数
 * @param getters：变成 computed 的对象集合
 * @param actions: 变成 action 的对象集合
 */
export default function createAction<T extends TAnyObject, T2 extends _Method, T3 extends _Method>(
    id: TStateKey = Symbol('_action'),
    state: () => T,
    getters: T2,
    actions: T3,
  ) {

  // 创建实例
  const tmp = new Model<T>(state, id)
  // 套上 reactive 
  const ret = reactive(tmp)
 
  // 挂载 getters，变成 computed
  if (typeof getters === 'object') {
    Object.keys(getters).forEach(key => {
      // 在实例上面挂载 computed
      Object.defineProperty(tmp, key, {
        value: markRaw(computed(() => {
          const re = (getters as TAnyObject)[key].call(ret, ret)
          return re
        })),
        writable: true
      })
    })
  }

  // 挂载 actions
  if (typeof actions === 'object') {
    Object.keys(actions).forEach(key => {
      // 在实例上面挂载 action
      Object.defineProperty(tmp, key, {
        value: async function (...arg: Array<any>) {
          const fun = (actions as TAnyObject)[key]
          if (fun.toString().match(/^\(.*\) => \{/)) {
            // 箭头函数
            await (actions as TAnyObject)[key].call(ret, ret, ...arg)
          } else {
            // 普通函数
            await (actions as TAnyObject)[key].call(ret as T, ...arg)
          }
        },
        writable: true
      })
 
    })
  }

  // type Gets = Partial<T2>
  // type actions = Partial<T3>
  // type Getters2 = Pick<IStateCreateOption, 'getters'>
  // type Getters3 = typeof info.getters

  // type Getters = Partial<_ActionsTree>
  
  return ret  as T & IModel<T> & T2 & T3// & Gets
}